#!/bin/sh -efu

gear_update_subdir() # test entry point
{
	local suffix result msg diff_output diff_subdir long_move short_move

	if [ "$gear_subdir" = '.' ]; then
		diff_subdir=
	else
		diff_subdir="$gear_subdir/"
	fi

	diff_output="\
 ${diff_subdir}contents-changed-file | 2 +-
 ${diff_subdir}mode-changed-file     | 0
 ${diff_subdir}new-file              | 1 +
 ${diff_subdir}old-file              | 1 -
 4 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/${diff_subdir}contents-changed-file b/${diff_subdir}contents-changed-file
index fdcdef8..9ee6f88 100644
--- a/${diff_subdir}contents-changed-file
+++ b/${diff_subdir}contents-changed-file
@@ -1 +1 @@
-This is changed file.
+This is changed file and it is changed.
diff --git a/${diff_subdir}mode-changed-file b/${diff_subdir}mode-changed-file
old mode 100644
new mode 100755
diff --git a/${diff_subdir}new-file b/${diff_subdir}new-file
new file mode 100644
index 0000000..0cb9c72
--- /dev/null
+++ b/${diff_subdir}new-file
@@ -0,0 +1 @@
+This is new file.
diff --git a/${diff_subdir}old-file b/${diff_subdir}old-file
deleted file mode 100644
index d265e35..0000000
--- a/${diff_subdir}old-file
+++ /dev/null
@@ -1 +0,0 @@
-This is old file."

	mkdir -p .git/.work
	pushd .git/.work>/dev/null
	mkdir subdir-1.2.3
	cat <<-EOF >subdir-1.2.3/file
	This is file.
	EOF
	cat <<-EOF >subdir-1.2.3/old-file
	This is old file.
	EOF
	cat <<-EOF >subdir-1.2.3/contents-changed-file
	This is changed file.
	EOF
	cat <<-EOF >subdir-1.2.3/mode-changed-file
	This file will change mode.
	EOF
	case "$gear_type" in
		'')
		cp -a subdir-1.2.3 initial-import
		;;
		.gem)
		tar -czf data.tar.gz -C subdir-1.2.3 .
		echo "This is metadata." | gzip -c > metadata.gz
		tar cf initial-import.gem data.tar.gz metadata.gz
		;;
		*)
		find subdir-1.2.3 -type f -print| $gear_compress| $gear_filter> "initial-import$gear_type" 2>/dev/null
		;;
	esac

	rm -rf subdir-1.2.3
	mkdir subdir-1.2.3
	cat <<-EOF >subdir-1.2.3/file
	This is file.
	EOF
	cat <<-EOF >subdir-1.2.3/new-file
	This is new file.
	EOF
	cat <<-EOF >subdir-1.2.3/contents-changed-file
	This is changed file and it is changed.
	EOF
	cat <<-EOF >subdir-1.2.3/mode-changed-file
	This file will change mode.
	EOF
	chmod 755 subdir-1.2.3/mode-changed-file
	case "$gear_type" in
		'') ;; # do nothing
		.gem)
		tar -czf data.tar.gz -C subdir-1.2.3 .
		echo "This is metadata." | gzip -c > metadata.gz
		tar cf subdir-1.2.3.gem data.tar.gz metadata.gz
		;;
		*)
		find subdir-1.2.3 -type f -print| $gear_compress| $gear_filter> "subdir-1.2.3$gear_type" 2>/dev/null
		;;
	esac
	cp -a "subdir-1.2.3$gear_type" "subdir-1.2.3.left_extension"
	popd>/dev/null

	if [ "$gear_subdir" = '.' ]; then
		gear-update ".git/.work/initial-import$gear_type" "$gear_subdir"
	else
		gear-update -c ".git/.work/initial-import$gear_type" "$gear_subdir"
	fi
	git commit -q -a -m 'Initial import'

	mkdir -p .gear/tags .gear-tags
	touch .gear-rules .gear/rules .gear-tags/list .gear/tags/list
	git add .gear-rules .gear/rules .gear-tags/list .gear/tags/list
	git commit -q -a -m 'Gearified'

	for suffix in "$gear_type" ".left_extension"; do
		gear-update ".git/.work/subdir-1.2.3$suffix" "$gear_subdir"

		result="$(git diff -p --stat)"
		assertEquals "should not alter work tree" "" "$result"

		result="$(git diff -p --stat --cached)"
		assertEquals "should update index" "$diff_output" "$result"

		git reset -q --hard HEAD
	done

	if [ "$gear_type" != "" -a "$gear_type" != ".gem" ]; then
		for suffix in "$gear_type" ".left_extension"; do
			gear-update -s subdir-1.2.3 ".git/.work/subdir-1.2.3$suffix" "$gear_subdir"

			result="$(git diff -p --stat)"
			assertEquals "should not alter work tree" "" "$result"

			result="$(git diff -p --stat --cached)"
			assertEquals "should update index" "$diff_output" "$result"

			git reset -q --hard HEAD
		done
	fi

	case "$gear_type" in
		'')
		msg="gear-update-src-dir: Cannot use --subdir for updating from a directory source.
FAIL"
		;;
		.gem)
		msg="gear-update-src-gem: Cannot use --subdir for updating from a gem source.
FAIL"
		;;
		*)
		msg="gear-update: WORKDIR/.git/.work/subdir-1.2.3$gear_type: directory \`non-existant-subdir' not found in archive.
FAIL"
		;;
	esac
	result="$((gear-update -s non-existant-subdir ".git/.work/subdir-1.2.3$gear_type" "$gear_subdir" 2>&1 && echo OK || echo FAIL) | sed -e "s#$(quote_sed_regexp "$workdir/")#WORKDIR/#g")"
	assertEquals "should not update non-existant directory" "$msg" "$result"

	assertEquals "should not alter anything on error" "" "$(git diff -p --stat)$(git diff -p --stat --cached)"

	touch "$gear_subdir"/left-file
	result="$((gear-update ".git/.work/subdir-1.2.3$gear_type" "$gear_subdir" 2>&1 && echo OK || echo FAIL) | sed -e "s#$(quote_sed_regexp "$workdir/")#WORKDIR/#g")"
	assertEquals "should fail on untracked files" "gear-update: $gear_subdir: Untracked or modified files found.
FAIL" "$result"

	git reset -q --hard HEAD

	touch "$gear_subdir"/left-file
	git add "$gear_subdir"/left-file
	result="$((gear-update ".git/.work/subdir-1.2.3$gear_type" "$gear_subdir" 2>&1 && echo OK || echo FAIL) | sed -e "s#$(quote_sed_regexp "$workdir/")#WORKDIR/#g")"
	assertEquals "should fail on new files" "gear-update: $gear_subdir: Changed files found in the index.
FAIL" "$result"

	git reset -q --hard HEAD

	rm -f "$gear_subdir"/file
	result="$((gear-update ".git/.work/subdir-1.2.3$gear_type" "$gear_subdir" 2>&1 && echo OK || echo FAIL) | sed -e "s#$(quote_sed_regexp "$workdir/")#WORKDIR/#g")"
	assertEquals "should fail on deleted files" "gear-update: $gear_subdir: Untracked or modified files found.
FAIL" "$result"

	git reset -q --hard HEAD

	echo "Modified file." > "$gear_subdir"/file
	result="$((gear-update ".git/.work/subdir-1.2.3$gear_type" "$gear_subdir" 2>&1 && echo OK || echo FAIL) | sed -e "s#$(quote_sed_regexp "$workdir/")#WORKDIR/#g")"
	assertEquals "should fail on modified files" "gear-update: $gear_subdir: Untracked or modified files found.
FAIL" "$result"

	git reset -q --hard HEAD

	if [ -n "$diff_subdir" ]; then
		long_move="${diff_subdir}{ => subdir-1.2.3}/mode-changed-file"
		short_move="${diff_subdir}{ => subdir-1.2.3}/file"
	else
		long_move="mode-changed-file => subdir-1.2.3/mode-changed-file"
		short_move="file => subdir-1.2.3/file"
	fi
	diff_output="\
 $(printf %-${#long_move}s "${diff_subdir}contents-changed-file") | 1 -
 $(printf %-${#long_move}s "${diff_subdir}old-file") | 1 -
 $(printf %-${#long_move}s "${diff_subdir}subdir-1.2.3/contents-changed-file") | 1 +
 $(printf %-${#long_move}s "$short_move") | 0
 $long_move | 0
 $(printf %-${#long_move}s "${diff_subdir}subdir-1.2.3/new-file") | 1 +
 6 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/${diff_subdir}contents-changed-file b/${diff_subdir}contents-changed-file
deleted file mode 100644
index fdcdef8..0000000
--- a/${diff_subdir}contents-changed-file
+++ /dev/null
@@ -1 +0,0 @@
-This is changed file.
diff --git a/${diff_subdir}old-file b/${diff_subdir}old-file
deleted file mode 100644
index d265e35..0000000
--- a/${diff_subdir}old-file
+++ /dev/null
@@ -1 +0,0 @@
-This is old file.
diff --git a/${diff_subdir}subdir-1.2.3/contents-changed-file b/${diff_subdir}subdir-1.2.3/contents-changed-file
new file mode 100644
index 0000000..9ee6f88
--- /dev/null
+++ b/${diff_subdir}subdir-1.2.3/contents-changed-file
@@ -0,0 +1 @@
+This is changed file and it is changed.
diff --git a/${diff_subdir}file b/${diff_subdir}subdir-1.2.3/file
similarity index 100%
rename from ${diff_subdir}file
rename to ${diff_subdir}subdir-1.2.3/file
diff --git a/${diff_subdir}mode-changed-file b/${diff_subdir}subdir-1.2.3/mode-changed-file
old mode 100644
new mode 100755
similarity index 100%
rename from ${diff_subdir}mode-changed-file
rename to ${diff_subdir}subdir-1.2.3/mode-changed-file
diff --git a/${diff_subdir}subdir-1.2.3/new-file b/${diff_subdir}subdir-1.2.3/new-file
new file mode 100644
index 0000000..0cb9c72
--- /dev/null
+++ b/${diff_subdir}subdir-1.2.3/new-file
@@ -0,0 +1 @@
+This is new file."

	case "$gear_type" in
		'')
		msg="gear-update-src-dir: Cannot use --all for updating from a directory source.
FAIL"
		diff_output=""
		;;
		.gem)
		msg="gear-update-src-gem: Cannot use --all for updating from a gem source.
FAIL"
		diff_output=""
		;;
		*)
		msg="OK"
		;;
	esac
	result="$((gear-update -a ".git/.work/subdir-1.2.3$gear_type" "$gear_subdir" 2>&1 && echo OK || echo FAIL) | sed -e "s#$(quote_sed_regexp "$workdir/")#WORKDIR/#g")"
	assertEquals "should accept -a when allowed" "$msg" "$result"

	result="$(git diff -p --stat)"
	assertEquals "should not alter work tree" "" "$result"

	result="$(git diff -p --stat --cached)"
	assertEquals "should update index" "$diff_output" "$result"
}
